﻿using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Furion.RemoteRequest.Extensions;
using iWare.Wms.Core;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Serilog;

namespace iWare.Wms.Application.DING
{
    /// <summary>
    /// 钉钉服务
    /// </summary>
    [Route("api/DingDing")]
    [ApiDescriptionSettings("钉钉对接", Name = "钉钉服务", Order = 100)]

    public class DingDingService : IDynamicApiController, ITransient
    {
        private readonly IRepository<GoodsDelivery, MasterDbContextLocator> _goodsDeliveryRep; //送货单仓储
        private readonly IRepository<GoodsDeliveryDetails, MasterDbContextLocator> _goodsDeliveryDetailsRep; //送货单明细仓储
        private readonly IRepository<CollectDeliveryDetails, MasterDbContextLocator> _collectDeliveryDetailsRep; //收货单单明细仓储
        private readonly IRepository<QualityFeedbackDetails, MasterDbContextLocator> _qualityFeedbackDetailsRep; //质检反馈明细仓储
        private readonly IMemoryCache _memoryCache;

        #region 默认
        /// <summary>
        /// 默认
        /// </summary>
        /// <param name="goodsDeliveryRep"></param>
        /// <param name="goodsDeliveryDetailsRep"></param>
        /// <param name="collectDeliveryDetailsRep"></param>
        /// <param name="qualityFeedbackDetailsRep"></param>
        /// <param name="memoryCache"></param>
        public DingDingService(
             IRepository<GoodsDelivery, MasterDbContextLocator> goodsDeliveryRep,
             IRepository<GoodsDeliveryDetails, MasterDbContextLocator> goodsDeliveryDetailsRep,
             IRepository<CollectDeliveryDetails, MasterDbContextLocator> collectDeliveryDetailsRep,
             IRepository<QualityFeedbackDetails, MasterDbContextLocator> qualityFeedbackDetailsRep,
             IMemoryCache memoryCache
            )
        {
            _goodsDeliveryRep = goodsDeliveryRep;
            _goodsDeliveryDetailsRep = goodsDeliveryDetailsRep;
            _collectDeliveryDetailsRep = collectDeliveryDetailsRep;
            _qualityFeedbackDetailsRep = qualityFeedbackDetailsRep;
            _memoryCache = memoryCache;
        }
        #endregion

        /// <summary>
        /// 根据送货单号查询收货
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetDeliveryDetailsByNo")]
        [NonUnify]
        [AllowAnonymous]
        public async Task<DeliveryOutput> GetDeliveryDetailsByNo([FromQuery] DeliverySearchByDeliveryNoInput input)
        {
            if (string.IsNullOrEmpty(input.DeliveryNo)) throw Oops.Oh("请扫描送货单号！");

            var deliveryDetailsList = await _collectDeliveryDetailsRep.DetachedEntities
                .Where(p => p.CollectDelivery.DeliveryNo == input.DeliveryNo).ToListAsync();
            if (deliveryDetailsList.Count == 0) throw Oops.Oh("未查找到收货信息!");

            var materialList = new List<MaterialOutput>();

            foreach (var item in deliveryDetailsList)
            {
                if (item.IsQuality == YesOrNot.N)
                {
                    var material = new MaterialOutput()
                    {
                        ProjectCode = item.ProjectCode,
                        XuHao = item.XuHao,
                        Code = item.Code,
                        Name = item.Name,
                        SpecificationModel = item.SpecificationModel,
                        InspectionMethod = item.InspectionMethod,
                        Unit = item.Unit,
                        DeliveryQuantity = item.CollectQuantity,
                    };
                    materialList.Add(material);
                }
            };

            return new DeliveryOutput()
            {
                DeliveryNo = input.DeliveryNo,
                items = materialList
            };
        }

        /// <summary>
        /// 根据送货单号查询收货
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetDeliveryDetailsByNoAll")]
        [NonUnify]
        [AllowAnonymous]
        public async Task<DeliveryOutput> GetDeliveryDetailsByNoAll([FromQuery] DeliverySearchByDeliveryNoInput input)
        {
            if (string.IsNullOrEmpty(input.DeliveryNo)) throw Oops.Oh("请扫描送货单号！");

            var deliveryDetailsList = await _collectDeliveryDetailsRep.DetachedEntities
                .Where(p => p.CollectDelivery.DeliveryNo == input.DeliveryNo).ToListAsync();
            if (deliveryDetailsList.Count == 0) throw Oops.Oh("未查找到收货信息!");

            var materialList = new List<MaterialOutput>();

            foreach (var item in deliveryDetailsList)
            {
                var material = new MaterialOutput()
                {
                    ProjectCode = item.ProjectCode,
                    XuHao = item.XuHao,
                    Code = item.Code,
                    Name = item.Name,
                    SpecificationModel = item.SpecificationModel,
                    InspectionMethod = item.InspectionMethod,
                    Unit = item.Unit,
                    DeliveryQuantity = item.CollectQuantity,
                };
                materialList.Add(material);
            };

            return new DeliveryOutput()
            {
                DeliveryNo = input.DeliveryNo,
                items = materialList
            };
        }

        /// <summary>
        /// 根据规格查询收货
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetDeliveryDetailsBySpecification")]
        [NonUnify]
        [AllowAnonymous]
        [UnifyResult(typeof(DeliveryOutput))]
        public async Task<object> GetDeliveryDetailsBySpecification([FromQuery] DeliverySearchBySpecificationInput input)
        {
            if (string.IsNullOrEmpty(input.Specification)) throw Oops.Oh("请扫描规格！");

            var deliveryDetailsList = await _goodsDeliveryDetailsRep.DetachedEntities
                .Where(p => p.SpecificationModel == input.Specification).ProjectToType<GoodsDeliveryDetailsOutput>().ToListAsync();
            if (deliveryDetailsList.Count == 0) throw Oops.Oh("送货单号不存在!");

            // 先根据送货单号去重
            var deliveryDetailsDistinctList = deliveryDetailsList.Select(z => z.GoodsDelivery.DeliveryNo).Distinct().ToList();

            var list = new List<GoodsDeliveryDetailsOutput>();
            foreach (var deliveryNoItem in deliveryDetailsDistinctList)
            {
                var collectDeliveryDetails = await _collectDeliveryDetailsRep.FirstOrDefaultAsync(z => z.CollectDelivery.DeliveryNo == deliveryNoItem);
                if (collectDeliveryDetails == null && collectDeliveryDetails.IsQuality == YesOrNot.N) //未收货未质检
                {
                    var notCollectList = deliveryDetailsList.Where(z => z.GoodsDelivery.DeliveryNo == deliveryNoItem);
                    foreach (var item in notCollectList)
                    {
                        list.Add(item);
                    }
                }
                else if (collectDeliveryDetails != null && collectDeliveryDetails.IsQuality == YesOrNot.N) //已收货未质检
                {
                    var notCollectList = deliveryDetailsList.Where(z => z.GoodsDelivery.DeliveryNo == deliveryNoItem);
                    foreach (var item in notCollectList)
                    {
                        list.Add(item);
                    }
                }
                else continue;
            }

            var deliveryNoList = list.Select(z => z.GoodsDelivery.DeliveryNo).Distinct().ToList();
            if (deliveryNoList.Count > 1) return XnRestfulResultProvider.RESTfulMesaage("该规格对应多个送货单信息,请重新操作！");
            return XnRestfulResultProvider.RESTfulResult(new DeliveryOutput()
            {
                DeliveryNo = list.FirstOrDefault().GoodsDelivery.DeliveryNo,
                items = list.Adapt<List<MaterialOutput>>()
            }
            );
        }

        /// <summary>
        /// 获取质检后的送货单号
        /// </summary>
        /// <returns></returns>
        [HttpGet("ReturnDeliveryNo")]
        [AllowAnonymous]
        public async Task ReturnDeliveryNo([FromQuery] DeliveryNoInput input)
        {
            // 写日志文件
            Log.Error("[ReturnDeliveryNo][DeliveryNo:]" + input.DeliveryNo);

            var collectDeliveryDetails = await _collectDeliveryDetailsRep.DetachedEntities
                .Where(p => p.CollectDelivery.DeliveryNo == input.DeliveryNo).ProjectToType<MaterialOutput>().ToListAsync();
            if (collectDeliveryDetails.Count == 0) throw Oops.Oh("未查找到收货信息!");

            //质检操作
            var response = await "https://api.dingtalk.com/v1.0/yida/forms/instances/search"
                                        .SetHttpMethod(System.Net.Http.HttpMethod.Post)
                                        .SetHeaders(new Dictionary<string, object> {
                                                { "x-acs-dingtalk-access-token", GetAccessToken()},
                                        })
                                        .SetBody(new Dictionary<string, object> {
                                                { "systemToken", "3L966J7194R41Z80E6B0C8QW0A9R3R8FRBM9LU21" },
                                                { "searchFieldJson", "{\"textField_l9qmo4sl\": "+input.DeliveryNo+"}" },
                                                { "formUuid", "FORM-RK966E71SAC7FWE5D94KY67A88HB2Y5DGY0DLQ"},//"FORM-K5A66M71JVY4JOKRAC1UY9JFCMG43CMQNMQ9LK" 
                                                { "userId", "01234516621139759" },
                                                { "appType", "APP_H63D59RTBUA54YVG8WQN" }
                                        }, "application/json")
                                        .PostAsAsync<RootResult>();
            // 写日志文件
            Log.Error($"[ReturnDeliveryNo][DeliveryNo:{input.DeliveryNo}][response:]" + response.ToJson());

            if (response.totalCount > 0)
            {
                if (response.data.Count() > 0)
                {
                    var data = response.data[0];
                    if (data != null)
                    {
                        foreach (var item in data.formData.tableField_l9qmo4sn)
                        {
                            if (item.selectField_l9qmo4su == "不合格" && data.formData.radioField_l9qmo4sw == "同意让步接收") 
                                item.selectField_l9qmo4su = "让步接收";
                            if (item.selectField_l9qmo4su == "不合格" && data.formData.radioField_l9qmo4sw == "拒绝让步接收")
                                item.selectField_l9qmo4su = "退货";
                            var collectDeliveryDetailModel = await _collectDeliveryDetailsRep.FirstOrDefaultAsync(n =>
                            n.CollectDelivery.DeliveryNo == input.DeliveryNo && n.Code == item.textField_laki7n3o);
                            if (collectDeliveryDetailModel != null)
                            {
                                collectDeliveryDetailModel.IsQuality = YesOrNot.Y;
                                collectDeliveryDetailModel.QualityResult = GetQualityResult(item.selectField_l9qmo4su);
                                collectDeliveryDetailModel.QualityNumber = item.numberField_l9qmo4sy;
                                collectDeliveryDetailModel.AbnormalCause = item.multiSelectField_lcptssei != null && item.multiSelectField_lcptssei.Count > 0 ? string.Join(",", item.multiSelectField_lcptssei) : "N/A";
                                await _collectDeliveryDetailsRep.UpdateAsync(collectDeliveryDetailModel);
                            }
                        }

                        // 查询送货详情
                        var goodsDeliveryDetails = await _goodsDeliveryDetailsRep.DetachedEntities.Where(z => z.GoodsDelivery.DeliveryNo == input.DeliveryNo).ToListAsync();
                        foreach (var item in goodsDeliveryDetails)
                        {
                            var material = data.formData.tableField_l9qmo4sn.FirstOrDefault(z => z.textField_laki7n3o == item.Code);

                            if (material != null)
                            {
                                if (material.selectField_l9qmo4su == "不合格" && data.formData.radioField_l9qmo4sw == "同意让步接收")
                                    material.selectField_l9qmo4su = "让步接收";
                                if (material.selectField_l9qmo4su == "不合格" && data.formData.radioField_l9qmo4sw == "拒绝让步接收")
                                    material.selectField_l9qmo4su = "退货";

                                var qualityFeedbackDetails = await _qualityFeedbackDetailsRep.FirstOrDefaultAsync(z => z.DeliveryNo == input.DeliveryNo
                                && z.ProjectCode == item.ProjectCode && z.Code == item.Code && z.SpecificationModel == item.SpecificationModel);

                                // 查询是否有质检结果，不存在则添加，存在则更新质检信息
                                if (qualityFeedbackDetails == null)
                                {
                                    var model = new QualityFeedbackDetails()
                                    {
                                        DeliveryNo = input.DeliveryNo,
                                        SupperCode = (await _goodsDeliveryRep.FirstOrDefaultAsync(n => n.DeliveryNo == input.DeliveryNo)).SuppCode,
                                        ProjectCode = item.ProjectCode,
                                        Code = item.Code,
                                        Name = item.Name,
                                        SpecificationModel = item.SpecificationModel,
                                        QualityResult = GetQualityResult(material.selectField_l9qmo4su),
                                        QualityNumber = material.numberField_l9qmo4sy,
                                        AbnormalCause = material.multiSelectField_lcptssei != null && material.multiSelectField_lcptssei.Count > 0 ? string.Join(",", material.multiSelectField_lcptssei) : "N/A",
                                    IsAdminRead = YesOrNot.N,
                                        IsSupperRead = YesOrNot.N,
                                        CreatedTime = DateTimeOffset.Now
                                    };
                                    await _qualityFeedbackDetailsRep.InsertAsync(model);
                                }
                                else
                                {
                                    qualityFeedbackDetails.QualityResult = GetQualityResult(material.selectField_l9qmo4su);
                                    qualityFeedbackDetails.QualityNumber = material.numberField_l9qmo4sy;
                                    qualityFeedbackDetails.AbnormalCause = material.multiSelectField_lcptssei != null && material.multiSelectField_lcptssei.Count > 0 ? string.Join(",", material.multiSelectField_lcptssei) : "N/A";
                                    await _qualityFeedbackDetailsRep.UpdateAsync(qualityFeedbackDetails);
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 获取质检部的ID
        /// </summary>
        /// <returns></returns>
        [HttpGet("ReturnId")]
        [AllowAnonymous]
        public async Task ReturnId([FromQuery] DeliveryIdInput input)
        {
            // 写日志文件
            Log.Error("[ReturnId][DeliveryId:]" + input.Id);

            string url =  "https://api.dingtalk.com/v1.0/yida/forms/instances/" + input.Id + "?appType=APP_H63D59RTBUA54YVG8WQN&systemToken=3L966J7194R41Z80E6B0C8QW0A9R3R8FRBM9LU21&userId=01234516621139759";

            //质检操作
            var response = await url.SetHeaders(new Dictionary<string, object> {
                                                { "x-acs-dingtalk-access-token", GetAccessToken()},
                                        })
                                        .GetAsAsync<RootResultId>();
            // 写日志文件
            Log.Error($"[ReturnId][DeliveryId:{input.Id}][response:]" + response.ToJson());

            var data = response.formData;

            var collectDeliveryDetails = await _collectDeliveryDetailsRep.DetachedEntities
                .Where(p => p.CollectDelivery.DeliveryNo == data.textField_l9qmo4sl.ToString()).ProjectToType<MaterialOutput>().ToListAsync();
            if (collectDeliveryDetails.Count == 0) throw Oops.Oh("未查找到收货信息!");

            if (data != null)
            {
                foreach (var item in data.tableField_l9qmo4sn)
                {
                    if (item.selectField_l9qmo4su == "不合格" && data.radioField_l9qmo4sw == "同意让步接收")
                        item.selectField_l9qmo4su = "让步接收";
                    if (item.selectField_l9qmo4su == "不合格" && data.radioField_l9qmo4sw == "拒绝让步接收")
                        item.selectField_l9qmo4su = "退货";

                    var collectDeliveryDetailModel = await _collectDeliveryDetailsRep.FirstOrDefaultAsync(n =>
                    n.CollectDelivery.DeliveryNo == data.textField_l9qmo4sl.ToString() && n.Code == item.textField_laki7n3o);
                    if (collectDeliveryDetailModel != null)
                    {
                        collectDeliveryDetailModel.IsQuality = YesOrNot.Y;
                        collectDeliveryDetailModel.QualityResult = GetQualityResult(item.selectField_l9qmo4su);
                        collectDeliveryDetailModel.QualityNumber = item.numberField_l9qmo4sy;
                        collectDeliveryDetailModel.AbnormalCause = item.multiSelectField_lcptssei != null && item.multiSelectField_lcptssei.Count > 0 ? string.Join(",", item.multiSelectField_lcptssei) : "N/A";
                        await _collectDeliveryDetailsRep.UpdateAsync(collectDeliveryDetailModel);
                    }
                }

                // 查询送货详情
                var goodsDeliveryDetails = await _goodsDeliveryDetailsRep.DetachedEntities.Where(z => z.GoodsDelivery.DeliveryNo == data.textField_l9qmo4sl.ToString()).ToListAsync();

                foreach (var item in goodsDeliveryDetails)
                {
                    var material = data.tableField_l9qmo4sn.FirstOrDefault(z => z.textField_laki7n3o == item.Code);
                    
                    if (material != null)
                    {
                        if (material.selectField_l9qmo4su == "不合格" && data.radioField_l9qmo4sw == "同意让步接收")
                            material.selectField_l9qmo4su = "让步接收";
                        if (material.selectField_l9qmo4su == "不合格" && data.radioField_l9qmo4sw == "拒绝让步接收")
                            material.selectField_l9qmo4su = "退货";

                        var qualityFeedbackDetails = await _qualityFeedbackDetailsRep.FirstOrDefaultAsync(z => z.DeliveryNo == data.textField_l9qmo4sl.ToString()
                        && z.Code == item.Code && z.SpecificationModel == item.SpecificationModel);

                        if (material.selectField_l9qmo4su != "不合格")
                        {
                            // 查询是否有质检结果，不存在则添加，存在则更新质检信息
                            if (qualityFeedbackDetails == null)
                            {
                                var model = new QualityFeedbackDetails()
                                {
                                    DeliveryNo = data.textField_l9qmo4sl.ToString(),
                                    SupperCode = (await _goodsDeliveryRep.FirstOrDefaultAsync(n => n.DeliveryNo == data.textField_l9qmo4sl.ToString())).SuppCode,
                                    ProjectCode = item.ProjectCode,
                                    Code = item.Code,
                                    Name = item.Name,
                                    SpecificationModel = item.SpecificationModel,
                                    QualityResult = GetQualityResult(material.selectField_l9qmo4su),
                                    QualityNumber = material.numberField_l9qmo4sy,
                                    AbnormalCause = material.multiSelectField_lcptssei != null && material.multiSelectField_lcptssei.Count > 0 ? string.Join(",", material.multiSelectField_lcptssei) : "N/A",
                                    IsAdminRead = YesOrNot.N,
                                    IsSupperRead = YesOrNot.N,
                                    CreatedTime = DateTimeOffset.Now
                                };
                                await _qualityFeedbackDetailsRep.InsertAsync(model);
                            }
                            else
                            {
                                qualityFeedbackDetails.QualityResult = GetQualityResult(material.selectField_l9qmo4su);
                                qualityFeedbackDetails.QualityNumber = material.numberField_l9qmo4sy;
                                qualityFeedbackDetails.AbnormalCause = material.multiSelectField_lcptssei != null && material.multiSelectField_lcptssei.Count > 0 ? string.Join(",", material.multiSelectField_lcptssei) : "N/A";
                                await _qualityFeedbackDetailsRep.UpdateAsync(qualityFeedbackDetails);
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 获取AccessToken
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetAccessToken")]
        [NonUnify]
        [AllowAnonymous]
        public string GetAccessToken()
        {
            var token = _memoryCache.Get(CommonConst.DD_ACCESSTOKEN_CODE);
            if (token != null) return token.ToString();

            var response = "https://oapi.dingtalk.com/gettoken?appkey={appkey}&appsecret={appsecret}".
                                  SetTemplates(new Dictionary<string, object> {
                                                { "appkey", "dingdktlsxvypzpyqyyw" },
                                                { "appsecret", "BDPhaENcU9Y37zse-jxkpSJUDwWKLvLbrcAINLnJBrsoSfeNZg8bv-HAW1DJvqsY" }})
                                  .GetAsAsync<DingDingAccessToken>();

            if (response.Result.errcode == 0)
            {
                var cacheOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromSeconds(7200));
                _memoryCache.Set(CommonConst.DD_ACCESSTOKEN_CODE, response.Result.access_token, cacheOptions);
                return response.Result.access_token;
            }

            return response.Result.errmsg;
        }

        /// <summary>
        /// 获取质检数据
        /// </summary>
        /// <returns></returns>
        [HttpPost("GetQualityInspectionData")]
        [NonUnify]
        [AllowAnonymous]
        public async Task<object> GetQualityInspectionData()
        {
            var response = await "https://api.dingtalk.com/v1.0/yida/forms/instances/search"
                                        .SetHttpMethod(System.Net.Http.HttpMethod.Post)
                                        .SetHeaders(new Dictionary<string, object> {
                                                { "x-acs-dingtalk-access-token", GetAccessToken()},
                                        })
                                        .SetBody(new Dictionary<string, object> {
                                                { "systemToken", "3L966J7194R41Z80E6B0C8QW0A9R3R8FRBM9LU21" },
                                                { "searchFieldJson", "{\"textField_l9qmo4sl\": 361687675478085}" },
                                                { "formUuid", "FORM-RK966E71SAC7FWE5D94KY67A88HB2Y5DGY0DLQ"},//"FORM-K5A66M71JVY4JOKRAC1UY9JFCMG43CMQNMQ9LK" 
                                                { "userId", "01234516621139759" },
                                                { "appType", "APP_H63D59RTBUA54YVG8WQN" }
                                        }, "application/json")
                                        .PostAsAsync<RootResult>();
            return response;
        }

        /// <summary>
        /// 质检结果转换
        /// </summary>
        /// <param name="QualityResult"></param>
        /// <returns></returns>
        [NonAction]
        public QualityEnum GetQualityResult(string QualityResult)
        {
            switch (QualityResult)
            {
                case "合格":
                    return QualityEnum.HeGe;
                case "返修":
                    return QualityEnum.FanXiu;
                case "报废":
                    return QualityEnum.BaoFei;
                case "技术确认":
                    return QualityEnum.JiShu;
                case "让步接收":
                    return QualityEnum.RangBu;
                case "退货":
                    return QualityEnum.TuiHuo;
                case "免检":
                    return QualityEnum.MianJian;
                default:
                    return QualityEnum.MianJian;
            }
        }
    }
}
